'use strict';

angular.module('theApp', [
    'ngRoute',
    'firebase',
    'theApp.filters',
    'theApp.directives',
    'theApp.controllers',
    'theApp.routes'
])

.value('fbURL', 'https://ssw-ng1-1.firebaseio.com/')

.factory('ssw_service', function() {

    //order = ["user", "team", "request", "field"];

    var ssw_funcs = {


        preamble: function($rootScope, $firebase, fbURL) {
            $rootScope.genders = ['Boys', 'Girls'];
            $rootScope.ages = ['U8', 'U9', 'U10', 'U11', 'U12', 'U13', 'U14', 'U15', 'U17', 'U18', 'U19' ];
            $rootScope.classes = ['Recreational', 'Competitive'];            
            $rootScope.days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'];    
            $rootScope.fieldsall = $firebase(new Firebase(fbURL + 'fields')).$asArray();           
            //$rootScope.requestsall = $firebase(new Firebase(fbURL + 'requests')).$asArray();  
            
            $rootScope.errors = {
                "0"   : "Unknown error.", 
                "1000": "Cannot create team as guest or for another user.",
                "1001": "Attempt to load a non-existing record.",
                "1002": "Unable to update the unique id generator."
            };
        },

        type_specific: function($scope, type, me) {
            if (type === 'request') {
               $scope.fieldsall.forEach(function(f, i) {
                   if (f.id === me.field1.id) {
                       $scope.request.field1 = $scope.fieldsall[i];
                   }
                   if (f.id === me.field2.id) {
                       $scope.request.field2 = $scope.fieldsall[i];
                       //$scope.fields.requests[$scope.fieldsall[i]] = true;
                   }
               });
            }
            /*
            if (type === 'field') {
                $scope.requestsall.forEach(function(req) {
                    req.fields.forEach(function(f) {
                        if (f.id) {
                            var u = f.id == $scope.field.id;
                        }
                    });
                });
            }*/
        }, 

        add_new_parent: function($scope, type, pType, extra) {
            if ($scope[type][pType + 's'] === undefined) {
                $scope[type][pType + 's'] = {};
            }
            $scope[type][pType + 's'][extra] = true;        
        },

        type_specific_save_before: function($scope, type, ssw_service, parent) {

            if (parent !== undefined) {
                var pType = ssw_service.parent_of(type);
                ssw_service.add_new_parent($scope, type , pType, parent);
            }
            
            if (type === 'request') {
                
                // Add selected fields to 'request.fields' (not the same
                // as field1 and field2
                var x = {};
                x[$scope[type].field1.id] = 1;
                x[$scope[type].field2.id] = 2;
                $scope[type].fields = x;
            }
        },
        
        register_with_parent: function(type, pType, $firebase, fbURL, extra) {

            // Assign 'team.requests'
            //var team = 
            var rRef = new Firebase(fbURL + '/' + pType + 's/' + extra[0] + '/' + type + 's');   
            var reqs = $firebase(rRef).$asObject();
            reqs.$loaded().then(function(rr) {
                rr[extra[1]] = true;
                rr.$save().then(function(data) {
                }).catch(function(err) {
                    console.log(err);
                });
            });
        },

        child_of: function(type) {
            var pType = null;
            if (type === 'user') {
                pType = 'team';
            }
            else if (type === 'team') {
                pType = 'request';
            }
            else if (type === 'request') {
                pType = 'field';
            }
            return pType;
        },
        
        parent_of: function(type) {
            var pType = null;
            if (type === 'field') {
                pType = 'request';
            }
            else if (type === 'request') {
                pType = 'team';
            }
            else if (type === 'team') {
                pType = 'user';
            }
            return pType;
        },
        
        type_specific_save_after: function($scope, type, $firebase, fbURL, ssw_service, extra) {
            
            var pType = ssw_service.parent_of(type);
            if (pType === null) {
                return;
            }
            ssw_service.register_with_parent(type, pType, $firebase, fbURL, extra);
        },
        
        /*
                // Assign 'team.requests'
                //var team = 
                var rRef = new Firebase(fbURL + 'teams/' + extra[0] + '/requests');   
                var reqs = $firebase(rRef).$asObject();
                reqs.$loaded().then(function(rr) {
                    rr[extra[1]] = true;
                    rr.$save().then(function(data) {
                    }).catch(function(err) {
                        console.log(err);
                    });
                });
            }
            if (type === 'user') {

                // Assign 'user.teams'
                //var team = 
                var rRef = new Firebase(fbURL + 'users/' + extra[0] + '/teams');   
                var reqs = $firebase(rRef).$asObject();
                reqs.$loaded().then(function(rr) {
                    rr[extra[1]] = true;
                    rr.$save().then(function(data) {
                    }).catch(function(err) {
                        console.log(err);
                    });
                });
            }
        },*/

        update_auth: function($rootScope, $firebase, $firebaseSimpleLogin, fbURL, ssw_service) {     
            $rootScope.lObj = $firebaseSimpleLogin(new Firebase(fbURL));
            $rootScope.lObj.$getCurrentUser().then(function(luser) { 
                if (luser !== null) {
                    console.log('Current user: ', luser.uid);
                    var users = $firebase(new Firebase(fbURL + 'users')).$asArray();
                    users.$loaded(function(data){
                        $rootScope.loggedUser = ssw_service.find_by_field(data, 'uid', luser.uid, true)[0];
                    });
                } else {
                    console.log('Current user: none');
                    $rootScope.loggedUser = null;
                }
            });
        },
        
        validate_form: function($scope, $rootScope, type) {
            var error  = '';
            if (type === 'request') {
                if ($scope.requestEditing === true) {
                    var r = $scope.request;
                    var sessnum = parseInt(r.sessions);
                    if (sessnum < 1 || sessnum > 3 || isNaN(sessnum)) {
                        error += "Number of sessions per week must be 1,2, or 3.";
                    }                    
                    var dayCount1 = 0;
                    var dayCount2 = 0;
                    $rootScope.days.forEach(function(d) {
                        if (r['day1' + d] === true) {
                            dayCount1 += 1;
                        }
                        if (r['day2' + d] === true) {
                            dayCount2 += 1;
                        }
                    });
                    if (dayCount1 !== sessnum || dayCount2 !== sessnum) {
                        error += "Requested days ("+dayCount1+' '+dayCount2+") do not match number of sessions per week = " + sessnum;
                    }
                    if (r.purpose !== 'Practice' && r.purpose !== 'Scrimmage') {
                        error += "Request purpose must be Scrimmage or Practice";
                    }
                }
            }
            if (error === '') {
                return true;
            }
            alert('*** ERROR IN FORM *** ' + error);
            return false;
        },
            
        /*
        match_key: function(a, b) {
            var x;
            if (a > b) {
                x = b + a;
            } else {
                x = a + b;
            }
            return x;    
        },*/
        
        find_by_field: function(list, field, value, one) {
            var ret = [];
            var elm = null;
            if (list instanceof Array) {
                for (var i = 0; i < list.length; i++) {
                    elm = list[i];
                    if (elm[field] == value) { 
                        ret.push(elm);     
                        if (one) {
                            return ret;
                        }
                    }
                }
                return ret;
            } 
            var keys = list.$getIndex();
            keys.forEach(function(key, i) {
                // use == because we compare string to number
                elm = list.$child(key);
                if (elm[field] === value+'') { 
                    ret.push(elm);
                        if (one) {
                            return;
                        }
                }
            });
            return ret;
        },
        
        controller_one:  function($scope, $rootScope, $firebase, $location, $route, fbURL, ssw_service, type, nextAction, id) {

            var saved = {};
            var savedinfo = {};
            
            $scope.edit = function(t) {
                saved = angular.copy($scope[t]);
                savedinfo = angular.copy($scope[t + 'info']);
                $scope[t + 'Editing'] = true;
            }; 
            
            $scope.cancel = function(t) {
                $scope[t] = angular.copy(saved);
                $scope[t + 'info'] = angular.copy(savedinfo);
                $scope[t + 'Editing'] = false;
                $route.reload();
            };

            $scope.destroy = function(t) {
                var yn = prompt("Are you sure you want to delete this " + t + "? Type YES if you are", "NO");
                if (yn === "YES") {
                    alert('*** WARNING *** Destruction of components is not supported yet');
                }
            };

            $scope.save = function(t) {

                ssw_service.type_specific_save_before($scope, type, ssw_service);

                if (!ssw_service.validate_form($scope, $rootScope, type)) {
                    return;
                }
                if (true === confirm("Save the changes?")) {
                    $scope[t].$save()
                        .then(function(x) {
                            $scope[t + 'Editing'] = false;
                            var p = $firebase(x).$asObject();
                            p.$loaded(function(me) {
                                $route.reload();
                                //alert('Information for this ' + t + ' was updated');
                            });
                        })
                        .catch(function(err) {
                            console.log(err);
                            $scope[t + 'Editing'] = false;
                            alert('*** ERROR *** \nInformation for this ' + t + 'was NOT updated');
                        });
                } else {
                    //alert("Changes not saved");
                }
            };            

            $scope[type + 'Detail'] = false;
            $scope[type] = {};
            
            var thingRef = new Firebase(fbURL + type + 's/' + id);
            thingRef.once('value', function(thingSnap) {
     
                if (thingSnap.val() === null) {
                    console.log(type + ' with id ' +  id + ' not found.');
                    $location.path('/error/1001');
                    
                } else {

                    // Valid current item
                    var thingSync = $firebase(thingRef);
                    var thing = thingSync.$asObject();
                    thing.$loaded(
                        function(me) {
                            console.log(me);

                            $scope[type] = me;
                            $scope[type + 'Detail'] = true;
                            $scope[type + 'Editing'] = false;
                            $scope[type + 's'] = [me];
                                                                                     
                            if (nextAction !== undefined) {
                                nextAction.apply(this, [[me]]);
                            }
                            
                            ssw_service.type_specific($scope, type, me);
                        },
                        function(err) {
                            console.log(err);
                        }
                    );
                }
            });
        },
        
        controller_some: function($scope, $firebase, $filter, fbURL, ssw_service, type, sources, nextAction, noParents) {

            $scope[type + 's'] = [];
                    
            if (!(sources instanceof Array)) {
                $scope[type + 's'] = $firebase(new Firebase(fbURL + type + 's')).$asArray();
                return;
            }
            
            if (noParents === true) {

                var v = [];
                var snaps = $firebase(new Firebase(fbURL + type + 's')).$asArray();
                var c = snaps.length;
                snaps.$loaded().then(function(rr) {
                    rr.forEach(function(r, j) {
                        // XXXXX this should have an inner loop on sources
                        if (r['fields'][sources[0].id] !== undefined) {
                            v.push(r);
                            //if (j === sources.length - 1) {
                               // $scope[type + 's'] = v;                          
                            //}
                        }
                    });
                    $scope[type + 's'] = v;
                    if (nextAction !== undefined) {
                        nextAction.apply(this, [v]);
                    }

                }).catch(function(err) {
                    console.log(err);
                });
                
                return;
            }
                

            // WARNING! The elements here must be collected synchronously
            // because we cannot go to the next action until all have been
            // gathered. To do this, I collect the snapshot synchronously
            // and then load them asynchronously but I count the callbacks
            // at the end, so I know when I am done.
            var v = [];
            var pos = 0;
            sources.forEach(function(client, j) {
                var ob = client[type + 's'];
                if (ob !== undefined) {                    
                    Object.keys(ob).map(function (e, i) {                        
                        v.push($firebase(new Firebase(fbURL + type + 's/' + e)).$asObject());
                        pos++;
                    });
                }
            });

            var w = [];
            var s = {};
            var c = v.length;
            v.forEach(function(x, i) {
                c--;
                x.$loaded().then(function(e) {
                    if (s[e.id] === undefined) {
                        s[e.id] = true;
                        w.push(e);
                    }
                    if (c === 0) {
                        $scope[type + 's'] = w;
                        if (nextAction !== undefined) {
                            nextAction.apply(this, [w]);
                        }
                    }
                }).catch(function(err) {
                    console.log(err);
                });
            });
                                
                             
                    /*
                    $firebase(new Firebase(fbURL + type + 's')).$asArray().$loaded().then(function(rr) {
                        rr.forEach(function(r, i) {
                            if (r['fields'][sources[j].id] !== undefined) {
                                v.push(r);
                            }
                            if (j === sources.length - 1) {
                                $scope[type + 's'] = v;
                          
                                if (nextAction !== undefined) {
                                    nextAction.apply(this, [v]);
                                }
                            }
                        });
                    }).catch(function(err) {
                        console.log(err);
                    });

                } else {
                
                    
                }*/
                    
          
        },

        set_defaults: function($scope, type) {
            $scope[type] = {};
            if (type === 'team') {
                $scope[type].name = 'A_Team';
                $scope[type].age = 'U14';
                $scope[type].gender = 'Boys';
                $scope[type].class = 'Recreational';
            }
        },
        
        controller_create: function($scope, $rootScope, $firebase, $location, $route, parent, fbURL, ssw_service, type) {   

            var list = $firebase(new Firebase(fbURL + type + 's')).$asArray();
            $scope[type + 's'] = $firebase(new Firebase(fbURL + type + 's')).$asArray(); 
            
            $scope[type + 'Detail'] = true;
            $scope[type + 'Editing'] = true;
            
            ssw_service.set_defaults($scope, type);

            $scope.cancel = function() {
                $location.path('/' + ssw_service.parent_of(type) + '/' + parent);
            };

            $scope.save = function() {

                if (!ssw_service.validate_form($scope, $rootScope, type)) {  
                    return;
                }
                
                // custom actions such as relations with other objects
                ssw_service.type_specific_save_before($scope, type, ssw_service, parent);

                list.$add($scope[type]).then(function(ref) {
                    var id = ref.name();
                    console.log('Saved new object ', id, ' at ', list.$indexFor(id));
                        
                    // add unique id 
                    var countRef = new Firebase(fbURL + 'count_id');
                    countRef.transaction(function(count) {
                        return count+1;
                    },
                    function(error, committed, snap) {
                        
                        if (error) {
                            console.log('Unable to update count_id');
                            $location.path('/error/1002');
                            return;
                        }
                        var mapid = snap.val();
                      
                        console.log('New count: ', mapid);
                              
                        // add unique id and mapid
                        ref.update({
                           "mapid" : mapid,
                            "id" : id
                        });
                                
                        // custom actions such as relations with other objects
                        ssw_service.type_specific_save_after($scope, type, $firebase, fbURL, ssw_service, [parent, id]);
                            
                        console.log('New item was assigned unique id and self id: ', mapid);
                        $scope[type + 'Editing'] = false;
                                                        
                        $location.path('/' + type + '/' + id);
                        $route.reload();
                        
                        //alert('New ' + type + ' was created with ID ' + mapid);                     
                    });
                }).catch(function(err) {
                    console.log('Cannot add new object: ', err);
                    $location.path('/error');
                });
            };
            
            $rootScope.lObj.$getCurrentUser().then(function(luser) { 
                if (luser === null) {
                    //alert('Cannot create new ' + type + ' as guest');
                    $location.path('/error');
                }            
            });

        }
         
    };
    
    return ssw_funcs;
})


;

